import org.bytedeco.javacpp.Loader;
import org.bytedeco.javacpp.avcodec;
import org.bytedeco.javacpp.opencv_core;
import org.bytedeco.javacpp.opencv_objdetect;
import org.bytedeco.javacv.*;

import javax.swing.*;

import static org.bytedeco.javacpp.opencv_imgproc.*;
import static org.bytedeco.javacpp.opencv_imgproc.rectangle;

/**
 * javaCV开发详解之3：收流器实现，录制流媒体服务器的rtsp/rtmp视频文件(基于javaCV-FFMPEG)
 *
 * https://blog.csdn.net/eguid_1/article/details/52680802
 */
public class RecordCamera {


    public static void main(String args[]) throws Exception {
        recordCamera("e:\\output1.mp4",25);
    }

    /**
     * 录制视频
     * @param outputfile 录制的文件路径
     * @param frameRate  帧率----------每秒显示帧数
     */
    public static void recordCamera(String outputfile,double frameRate) throws Exception{
        Loader.load(opencv_objdetect.class);//--------------------这句话不懂
        FrameGrabber grabber = FrameGrabber.createDefault(0);
        grabber.start();//开启抓取器



        //视频转换器
        OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
        ////抓取一帧视频并将其转换为图像，至于用这个图像用来做什么？加水印，人脸识别等等自行添加
        Frame frame = grabber.grab();
        opencv_core.IplImage grabbedImage = converter.convert(frame);

        //获取第一帧的图片大小
        int width = grabbedImage.width();
        int height = grabbedImage.height();


        //开启录制视频
        FrameRecorder recorder = FrameRecorder.createDefault(outputfile,width,height);
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); // avcodec.AV_CODEC_ID_H264，编码
        recorder.setFormat("flv");//封装格式，如果是推送到rtmp就必须是flv封装格式
        recorder.setFrameRate(frameRate);  //帧率
        recorder.start();


        long startTime=0;
        long videoTS=0;
        CanvasFrame canvasFrame = new CanvasFrame("camera", CanvasFrame.getDefaultGamma() / grabber.getGamma());
        canvasFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        canvasFrame.setAlwaysOnTop(true);
//        Frame rotatedFrame=converter.convert(grabbedImage);//不知道为什么这里不做转换就不能推到rtmp


        while (canvasFrame.isVisible() && (frame = grabber.grab()) != null) {

            //--------这里检测人脸

            opencv_core.Mat scr = converter.convertToMat(frame);//将获取的frame转化成mat数据类型
            detectFace(scr);//人脸检测
            frame = converter.convert(scr);//将检测结果重新的mat重新转化为frame

            canvasFrame.showImage(frame);
            if (startTime == 0) {
                startTime = System.currentTimeMillis();
            }
            videoTS = 1000 * (System.currentTimeMillis() - startTime);
            recorder.setTimestamp(videoTS);
            recorder.record(frame);
            Thread.sleep(40);
        }
        canvasFrame.dispose();
        recorder.stop();
        recorder.release();
        grabber.stop();




    }


    /**
     * 人脸检测
     * @param src
     * @return
     */
    public static opencv_core.Mat detectFace(opencv_core.Mat src) {

        String path = "H:\\openCV\\face\\src\\main\\resources\\haarcascade_frontalface_alt.xml" ;

        opencv_objdetect.CascadeClassifier cascade = new opencv_objdetect.CascadeClassifier(path);//初始化人脸检测器


        opencv_core.Mat grayscr=new opencv_core.Mat();
        cvtColor(src,grayscr,COLOR_BGRA2GRAY);//摄像头是彩色图像，所以先灰度化下
        equalizeHist(grayscr,grayscr);//均衡化直方图
        opencv_core.RectVector faces=new opencv_core.RectVector();
        cascade.detectMultiScale(grayscr, faces);

        for(int i=0;i<faces.size();i++) {
            opencv_core.Rect face_i=faces.get(i);
            rectangle(src, face_i, new opencv_core.Scalar(0, 0, 255, 1));
        }
        return src;
    }

}
